package org.itboys.shop.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.itboys.admin.constant.AdminSessionConstant;
import org.itboys.admin.entity.BusinessCenter;
import org.itboys.admin.service.BusinessCenterService;
import org.itboys.commons.CommonConstants;
import org.itboys.commons.utils.ajax.AjaxUtils;
import org.itboys.commons.utils.servlet.ServletContextHolder;
import org.itboys.commons.utils.time.TimeUtils;
import org.itboys.framework.query.JsonPageUtils;
import org.itboys.framework.query.PageQueryUtils;
import org.itboys.framework.spring.controller.BaseController;
import org.itboys.mongodb.utils.page.Page;
import org.itboys.seller.constant.SellerConstants;
import org.itboys.seller.dto.SellerGetMoneyDTO;
import org.itboys.seller.entity.SellerBank;
import org.itboys.seller.entity.SellerGetMoneyRecord;
import org.itboys.seller.service.SellerBankService;
import org.itboys.seller.service.SellerGetMoneyService;
import org.itboys.shop.entity.OrderSellRecord;
import org.itboys.shop.entity.ShopSeller;
import org.itboys.shop.service.OrderSellService;
import org.itboys.shop.service.ShopSellerService;
import org.itboys.trade.dao.AdminAmountMapper;
import org.itboys.trade.dto.AdminIncomeDTO;
import org.itboys.trade.entity.Order;
import org.itboys.trade.entity.PrePay;
import org.itboys.trade.entity.mysql.AdminAmount;
import org.itboys.trade.entity.mysql.AdminAmountRecord;
import org.itboys.trade.service.OrderService;
import org.itboys.trade.service.PrePayService;
import org.itboys.trade.service.mysql.AdminAmountRecordService;
import org.itboys.trade.service.mysql.AdminAmountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by liangchong on 2016/7/23.
 */
@RestController
@RequestMapping("/finance/income")
public class IncomeController extends BaseController {

    @Resource
    private OrderSellService orderSellService;
    @Autowired
    private SellerGetMoneyService sellerGetMoneyService;
    @Autowired
    private SellerBankService sellerBankService;
    @Autowired
    private ShopSellerService shopSellerService;
    @Autowired
    private AdminAmountRecordService adminAmountRecordService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PrePayService prePayService;
    @Autowired
    private AdminAmountService adminAmountService;
    @Autowired
    private AdminAmountMapper adminAmountMapper;

    @RequestMapping("/toListVM")
    public ModelAndView toListVM(HttpServletRequest request, HttpServletResponse response) {
        return new ModelAndView("/finance/income-list");
    }

    @RequestMapping("/toGetMoneyListVM")
    public ModelAndView toGetMoneyListVM(HttpServletRequest request, HttpServletResponse response,Model model) {
        return new ModelAndView("/finance/seller-getmoney-list");
    }

    @ResponseBody
    @RequestMapping("/getMoneyList")
    public void getMoneyList(HttpServletRequest request,HttpServletResponse response){
        Page<SellerGetMoneyRecord> page = sellerGetMoneyService.pageQuery(request);
        List<SellerGetMoneyRecord> recordList = page.getData();
        List<SellerGetMoneyDTO> dtoList = recordList.stream().map(record -> {
            SellerGetMoneyDTO dto = new SellerGetMoneyDTO();
            dto.setId(record.getId());
            SellerBank bank = sellerBankService.getById(record.getBankCardId());
            ShopSeller seller = shopSellerService.getById(record.getSellerId());
            dto.setCardNum(bank.getCard());
            dto.setBankName(bank.getBankName());
            dto.setBranchBank(bank.getBranchBank());
            dto.setUserName(bank.getUserName());
            dto.setUserPhone(bank.getUserPhone());
            dto.setSellerName(seller.getName());
            dto.setMoney(record.getMoney() / 100.0f);
            AdminAmount adminAmount = adminAmountService.getByUserIdAndType(record.getSellerId(), AdminAmountRecord.objType_seller);
            if (adminAmount != null) {
                dto.setValidMoney(new BigDecimal(adminAmount.getLeftWithdrawAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
            } else {
                dto.setValidMoney(0f);
            }
            dto.setCommitIime(TimeUtils.format(new Date(record.getCt()), CommonConstants.DATE.FORMAT_DEFAULT));
            return dto;
        }).collect(Collectors.toList());
        JsonPageUtils.renderJsonPage(page.getTotal(),page.getTotalPages(), dtoList, response);
    }

    @RequestMapping("/list")
    public void list(Long sellerId, Long centerId,
                     HttpServletRequest request, HttpServletResponse response){
        //Page<OrderSellRecord> page = orderSellService.pageQuery(request);
        Map<String, Object> map = Maps.newHashMap();
        Map<String, Object> pageMap = PageQueryUtils.preparePage(request);
        if (sellerId != null) {
            map.put("objId", sellerId);
            map.put("objType", AdminAmountRecord.objType_seller);
        } else if (centerId != null) {
            map.put("objId", centerId);
            map.put("objType", AdminAmountRecord.objType_center);
        }
        long count = adminAmountRecordService.count(map);
        map.put("orderByKey", "create_time");
        long rowStart = (Long)pageMap.get(PageQueryUtils.ROW_START);
        int pageSize = (Integer)pageMap.get(PageQueryUtils.PAGE_SIZE);
        int pageNo = (Integer)pageMap.get(PageQueryUtils.PAGE_NO);
        map.put("rowStart", rowStart);
        map.put("pageSize", pageSize);
        List<AdminAmountRecord> records = adminAmountRecordService.list(map);
        List<Long> orderIds = records.stream().map(AdminAmountRecord::getOrderId).collect(Collectors.toList());
        List<AdminIncomeDTO> incomeDTOList = Lists.newArrayList();
        List<Order> orders = orderService.getByIds(orderIds);
        List<PrePay> prePays = prePayService.getPaysByOrderIds(orderIds);
        Map<Long, Order> id2OrderMap = orders.stream().collect(Collectors.toMap(Order::getId, p -> p));
        Map<Long, PrePay> id2PrePayMap = Maps.newHashMap();
        prePays.stream().forEach(p -> {
                id2PrePayMap.put(p.getOrderId(), p);
        });
        if (sellerId != null) {
            ShopSeller seller = shopSellerService.getById(sellerId);
            incomeDTOList = records.stream().map(p -> {
                AdminIncomeDTO dto = new AdminIncomeDTO();
                Order order = id2OrderMap.get(p.getOrderId());
                PrePay pay = id2PrePayMap.get(p.getOrderId());
                dto.setSellerName(seller.getShopName());
                dto.setPhoneNo(seller.getFreePhone());
                dto.setTradMoney(new BigDecimal(p.getTotalAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setOrderNo(order.getOrderNo());
                dto.setPayNo(pay.getThirdTradeNo());
                dto.setPayType(pay.getPayType());
                dto.setStatus(order.getStatus());
                dto.setPayTime(pay.getUt());
                dto.setTradeType(p.getTradeType());
                dto.setIncome(new BigDecimal(p.getIncome()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setExpenditure(new BigDecimal(p.getExpenditure()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setCommissionMoney(new BigDecimal(p.getTotalCommission()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                return dto;
            }).collect(Collectors.toList());
        } else if (centerId != null) {
            List<Long> sellerIds = orders.stream().filter(p -> p.getSellerId() != null).map(Order::getSellerId).collect(Collectors.toList());
            List<ShopSeller> sellers = shopSellerService.getByIds(sellerIds);
            Map<Long, ShopSeller> id2SellerMap = sellers.stream().collect(Collectors.toMap(ShopSeller::getId, p -> p));
            //BusinessCenter center = businessCenterService.getById(centerId);
            incomeDTOList = records.stream().map(p -> {
                AdminIncomeDTO dto = new AdminIncomeDTO();
                Order order = id2OrderMap.get(p.getOrderId());
                PrePay pay = id2PrePayMap.get(p.getOrderId());
                if (order.getSellerId() != null) {
                    ShopSeller seller = id2SellerMap.get(order.getSellerId());
                    if (seller != null) {
                        dto.setSellerName(seller.getShopName());
                        dto.setPhoneNo(seller.getFreePhone());
                    }
                }
                dto.setTradMoney(new BigDecimal(p.getTotalAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setOrderNo(order.getOrderNo());
                dto.setPayNo(pay.getThirdTradeNo());
                dto.setPayType(pay.getPayType());
                dto.setStatus(order.getStatus());
                dto.setPayTime(pay.getUt());
                dto.setTradeType(p.getTradeType());
                dto.setIncome(new BigDecimal(p.getIncome()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setExpenditure(new BigDecimal(p.getExpenditure()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                dto.setCommissionMoney(new BigDecimal(p.getTotalCommission()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).floatValue());
                return dto;
            }).collect(Collectors.toList());
        }
        Page<AdminIncomeDTO> page = new Page<>(incomeDTOList, pageNo, pageSize, count);
        JsonPageUtils.renderJsonPage(page.getTotalPages(), page.getData(), response);
    }

    @RequestMapping("/sellList")
    public void sellList(HttpServletRequest request, HttpServletResponse response){
        long centerId = (Long) ServletContextHolder.getSession().getAttribute(AdminSessionConstant.CENTER_ID);
        Page<OrderSellRecord> page = orderSellService.queryCenterSellRecord(request, centerId);
        JsonPageUtils.renderJsonPage(page.getTotalPages(), page.getData(), response);
    }

    /**
     * 审核通过提现申请
     * @param request
     * @param response
     */
    @RequestMapping("/passGetMoney")
    public void pass(Long id,
                     HttpServletRequest request,HttpServletResponse response){
        try {
            SellerGetMoneyRecord record = sellerGetMoneyService.getById(id);
            record.setStatus(SellerConstants.SellerGetMoneyStatus.PASS);
            int ret = adminAmountMapper.updateSellerWithdraw(record.getSellerId(),
                    AdminAmountRecord.objType_seller, record.getMoney() * 1.0);
            if (ret != 1) {
                logger.error("update seller {} leftwithdraw error!", record.getSellerId());
                AjaxUtils.renderText(response, CommonConstants.FAIL);
                return;
            }
            sellerGetMoneyService.update(record);
            AjaxUtils.renderText(response, CommonConstants.SUCCESS);
        } catch (Exception e) {
            logger.error("/product/product/pass error", e);
            AjaxUtils.renderText(response, CommonConstants.FAIL);
        }
    }

    /**
     * 审核拒绝提现申请
     * @param request
     * @param response
     */
    @RequestMapping("/refuseGetMoney")
    public void refuseGetMoney(Long id,
                     HttpServletRequest request,HttpServletResponse response){
        try {
            SellerGetMoneyRecord record = sellerGetMoneyService.getById(id);
            record.setStatus(SellerConstants.SellerGetMoneyStatus.REFUSE);
            sellerGetMoneyService.update(record);
            AjaxUtils.renderText(response, CommonConstants.SUCCESS);
        } catch (Exception e) {
            logger.error("/product/product/pass error", e);
            AjaxUtils.renderText(response, CommonConstants.FAIL);
        }
    }
}
